# !/usr/bin/env python
# -*-coding:utf-8 -*-

"""
# File       : menu_node_view.py
# Time       ：2023/9/5 21:49
# Author     ：YangYong
# version    ：python 3.10
# Description：
    插件节点信息视图
"""
from typing import List, Set

from flask import request

from apis.flow import flow_ns
from apis.flow.schema.task_node_schema import PluginNodeInfoSchema
from apis.plugin.models.plugin_info import PluginInfo

from public.api_utils.api_decorator import handle_api_error
from public.base_model import db
from public.base_response import generate_response
from public.base_view import AbstractView


class NodeMenuView(AbstractView):
    url = '/node_menu'

    def __init__(self, *args, **kwargs):
        super(NodeMenuView, self).__init__(*args, **kwargs)
        self.form_data = request.args
        self.exclude_nodes = ['邮件插件']
        self.base_node_title = ['开始节点', '结束节点', '延时节点', '子流程', '标记节点']
        self.plugin_nodes = list()

    @staticmethod
    def get_nodes_type(title, plugin_info):
        for item in plugin_info:
            if item.get('title') == title:
                return item.get('class_name')
        return ''

    @staticmethod
    def get_nodes(title, plugin_info):
        return [
            {
                'text': item.get('text'),
                'type': item.get('type'),
                'background': item.get('background'),
                'method_name': item.get('method_name'),
                'version': item.get('version'),
                'class_name': item.get('class_name'),
                'task_type': item.get('task_type'),
            }
            for item in plugin_info
            if item.get('title') == title
        ]

    @staticmethod
    def get_node(nodes: List[dict], title: str):
        return next((node for node in nodes if node.get('text') == title), None)

    @staticmethod
    def get_node_icon(category: str, plugin_info: List[dict]):
        """获取节点icon"""
        for item in plugin_info:
            if item.get('category') == category:
                return item.get('icon')
        return 'LocationFilled'

    def get_menu_nodes(self):
        """获取任务菜单的节点顺序"""
        objs = db.session.query(PluginInfo).filter(
            PluginInfo.title.notin_(self.exclude_nodes),
            PluginInfo.active == 1
        ).all()

        plugin_info = PluginNodeInfoSchema().dump(objs, many=True)[::-1]
        category_list = set([item.get('category') for item in plugin_info])
        order_category_list = ['基础节点', '流程网关', '内置功能', '自动化测试', 'devops']
        order_category = order_category_list + [item for item in category_list if item not in order_category_list]
        for category in order_category:
            category_objs = db.session.query(PluginInfo).filter(PluginInfo.category == category).all()
            plugin_info = PluginNodeInfoSchema().dump(category_objs, many=True)
            titles = set([item.get('title') for item in plugin_info])
            nodes = self.helper(titles, plugin_info)
            icon = self.get_node_icon(category, plugin_info)
            if len(nodes) == 1:
                node = nodes.pop()
                node['icon'] = icon
            else:
                node = {
                    'title': category,
                    'nodes': nodes,
                    'nodesType': category,
                    'icon': icon
                }
            self.plugin_nodes.append(node)

    def helper(self, titles: Set[str], plugin_info: List[dict]):
        return [
            {
                'title': title,
                'nodesType': self.get_nodes_type(title, plugin_info),
                'nodes': self.get_nodes(title, plugin_info) if title != '基础节点' else [
                    self.get_node(self.get_nodes(title, plugin_info), _title) for _title in self.base_node_title
                ],
            }
            for title in titles
        ]

    @handle_api_error()
    @flow_ns.doc(description='获取任务菜单')
    def get(self):
        """获取任务菜单"""
        self.get_menu_nodes()
        return generate_response(self.plugin_nodes)
